/**
 */
package it.rainbowbreeze.polygen.data.webservice;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;

import it.rainbowbreeze.libs.helper.RainbowStreamHelper;
import it.rainbowbreeze.libs.net.RainbowRestfulClient;
import it.rainbowbreeze.polygen.common.LogFacility;

/**
 * @author Alfredo "Rainbowbreeze" Morresi
 *
 */
public class RestfulClient extends RainbowRestfulClient {
    // ------------------------------------------ Private Fields
    private static final String LOG_HASH = "RestfulClient";
    private final LogFacility mLogFacility;
    
    
    // -------------------------------------------- Constructors
    public RestfulClient(LogFacility logFacility) {
        super(logFacility);
        mLogFacility = logFacility;
    }
    
    
    // --------------------------------------- Public Properties
    
        
    // ------------------------------------------ Public Methods
    
    /**
     * Send a POST request to thotpot webservice. 

     * @param url - The server's address
     * @param data - The data you want to send
     * 
     * @throws IOException, ProtocolException
     */
    public ServerResponse postDataToWebservice(String url, Reader data)
    throws ProtocolException, IOException {
        StringWriter output = new StringWriter();
        
        ServerResponse response = postDataToWebservice(url, data, output);
        String messageBody = output.toString();
        
        mLogFacility.v(LOG_HASH, "Response body: " + messageBody);
        
        return new ServerResponse(
                response.getResponseCode(),
                response.getResponseMessage(),
                messageBody);
    }
    
    
    /**
     * Send a POST request to thotpot webservice. 

     * @param url - The server's address
     * @param data - The data you want to send
     * 
     * @throws IOException, ProtocolException
     */
    public ServerResponse postDataToWebservice(String url, String data)
    throws ProtocolException, IOException {
        StringReader readerData = new StringReader(data);
        
        mLogFacility.v(LOG_HASH, "Data to send: " + data);
        ServerResponse response = postDataToWebservice(url, readerData);
        return response;
    }
    
    // ----------------------------------------- Private Methods
      
    /**
     * Send a POST request to thotpot webservice. 

     * @param url - The server's address
     * @param data - The data you want to send
     * @param output - writes the server's response to output
     * 
     * @return server response with code end response message. Response body
     *         is piped to the output {@link Writer}
     * 
     * @throws IOException, ProtocolException
     */
    private ServerResponse postDataToWebservice(String url, Reader data, Writer output)
    throws ProtocolException, IOException {
        mLogFacility.v(LOG_HASH, "Sending POST request to " + url);
        HttpURLConnection connection = null;
        URL endpoint = new URL(url);
        try {
            connection = (HttpURLConnection) endpoint.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setAllowUserInteraction(false);
            //connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-type", "text/xml; charset=" + "UTF-8");
            OutputStream out = connection.getOutputStream();
            try {
                Writer writer = new OutputStreamWriter(out, "UTF-8");
                RainbowStreamHelper.pipe(data, writer);
                writer.close();
            } finally {
                if (out != null) out.close();
            }
             
            //Responses from the server (code and message)
            int serverResponseCode = connection.getResponseCode();
            String serverResponseMessage = connection.getResponseMessage();

            mLogFacility.v(LOG_HASH, "Request response: " +
                    "code: " + serverResponseCode + 
                    " - message: " + serverResponseMessage);

            InputStream in = connection.getInputStream();
            try {
                Reader reader = new InputStreamReader(in);
                RainbowStreamHelper.pipe(reader, output);
                reader.close();
            } finally {
                if (in != null)
                    in.close();
            }
            
            return new ServerResponse(serverResponseCode, serverResponseMessage);

        } finally {
            if (connection != null) connection.disconnect();
        }
        
    }
    
}
